Skip to main content

New Operators

Operator Aliases

These operators function the same, but they're more consistent with what's been standardized through programming today.

  • ! is an alias for not, the boolean inversion operator.
  • != is an alias for ~=, the inequality operator.

Compound Operators

A plethora of compound operators are available in Pluto:

  • Addition: +=
  • Subtraction: -=
  • Multiplication: *=
  • Float division: /=
  • Integer division: //=
  • Modulo: %=
  • Exponent: ^=
  • Bitwise AND: &=
  • Bitwise OR: |=
  • Bitwise XOR: ~=
    • In Lua, the inequality operator cannot be used in statements. It must be used in expressions. Because compound operators can only be used in statements (and cannot be used in expressions), this is not a compatibility break.
  • Bitshift left: <<=
  • Bitshift right: >>=
  • Concatenation: ..=
  • Nil-Coalescing: ??=
local a = 1
a = a + 1
a += 1
info

Compound operators are syntactic sugar. They'll call the same metamethods as their non-compound counterparts.

Coalescing Operator

The nil-coalescing operator is helpful for evaluating values against nil.

If the left-hand operand is nil, it returns the right-hand operand. Otherwise, it returns the left-hand operand.

local function say(message)
print(message ?? "The message was nil.")
end

say() --> The message was nil.
say(nil) --> The message was nil.
say("Hello, world!") --> Hello, world!

It's a cleaner version of this code:

local function say(message)
if message == nil then
message = "The message was nil."
end

print(message)
end

say() --> The message was nil.
say(nil) --> The message was nil.
say("Hello, world!") --> Hello, world!

You can even use compound assignment:

local function say(message)
message ??= "The message was nil."

print(message)
end

say() --> The message was nil.
say(nil) --> The message was nil.
say("Hello, world!") --> Hello, world!
info

This operator does not implement any metamethods.

Walrus Operator

The Walrus operator allows you to perform assignments inside of conditional expresssions.

if a := get_value() then
-- 'a' was assigned a truthy value.
else
-- 'a' was assigned a falsy value.
end

You can imagine it like this, but note they're not always the same:

do
local a = get_value()
if a then
-- 'a' was assigned a truthy value.
else
-- 'a' was assigned a falsy value.
end
end

Note that for while-loops, it will be executed as many times as the condition:

Pluto Way
while a := next_value() do
-- ...
end
Lua Way
while true do
local a = next_value()
if not a then break end
-- ...
end

Spaceship Operator

The spaceship operator, also known as the three-way comparison operator, allows you to quickly compare 2 values for equality and order.

local eq = 1 <=> 1
local lt = 3 <=> 42
local gt = 9 <=> 5
print(eq, lt, gt) --> 0, -1, 1

It works with any type that supports __eq and __lt, making it well-suited for usage in generic algorithms like sorting. The return values are designed such that you can compare them to 0, e.g. with the values from above:

print(eq <= 0) --> true
print(lt <= 0) --> true
print(gt <= 0) --> false

Pipe Operator

The pipe operator allows you represent data pipelines more succinctly.

local { http, json } = require "pluto:*"

http.request("https://httpbin.org/get")
|> json.decode
|> dumpvar
|> print

--> {
--> ["args"] = {},
--> ["headers"] = {
--> ["Host"] = string(11) "httpbin.org",
--> ["User-Agent"] = string(56) "Mozilla/5.0 (compatible; Soup Library; +https://soup.do)",
--> ["X-Amzn-Trace-Id"] = string(40) "Root=1-65e05b66-6aa8b7c94e7580774a804c24",
--> ["Accept-Encoding"] = string(13) "deflate, gzip",
--> },
--> ["origin"] = string(13) "1.2.3.4",
--> ["url"] = string(23) "https://httpbin.org/get",
--> }

Try It Yourself

The HTTP-to-print pipeline here would otherwise be written like this:

print(dumpvar(json.decode((http.request("https://httpbin.org/get")))))

Note that the pipe operator only passes on the first return value, which is classically achieved by wrapping the expression in an extra pair of parentheses.

Additional Arguments

It is also possible to provide additional arguments for the righthand side of the pipe operator:

local producer = || -> "10"

producer()
|> tonumber|16|
|> print --> 16

Try It Yourself

Methods Calls

There is specialized syntax for method calls with the pipe operator, too:

local producer = || -> 21

local obj = {
function multiply(value)
return value * self.factor
end
}
obj.factor = 2

producer()
|> obj:multiply
|> print --> 42

Try It Yourself

Anonymous Functions

The righthand side of the pipe operator can also be an anonymous function, allowing for more advanced usage like this:

local producer = || -> 42

producer()
|> |res| -> print($"The result was {res}")

--> The result was 42

Try It Yourself